/*
Copyright 2010 Iain Surgey.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

vec3 RWN_acceptpt, RWN_rejectpt;
float *RWN_minmaxs;
float RWN_minmaxs_trans[3];

#__body__

/*
================
R_RenderWorld
================
*/
private function R_RenderWorld ()
{
	c_drawnode = 0;
	currentmodel = #{&models[0]};
	R_RecursiveWorldNode (#{currentmodel->nodes}, 15);
}


/*
================
R_RecursiveWorldNode
================
*/
private function R_RecursiveWorldNode (node : Int, clipflags : Int)
{
	#{s| mnode_t *node}
	#{s| int clipflags}
	#{d| int			i, c, side, *pindex}
	#{d| mplane_t	*plane}
	#{d| msurface_t	*surf, **mark}
	#{d| float		d, dot}
	#{d| mleaf_t		*pleaf}
	
	if (#{node->contents} == CONTENTS_SOLID) {
		return;
	}
	
	if (#{node->visframe} != r_visframecount) {
		return;
	}
	
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
//  twice as fast in ASM
	if (clipflags != 0)
	{
		for (i in 0...4)
		{
			if ((clipflags & (1<<i)) == 0)
				continue;	// don't need to clip against it

		// generate accept and reject points
		// FIXME: do with fast look-ups or integer tests based on the sign bit
		// of the floating point values
			
			pindex = #{pfrustum_indexes[i]};
			#{RWN_rejectpt.p[0] = node->minmaxs[pindex[0]]};
			#{RWN_rejectpt.p[1] = node->minmaxs[pindex[1]]};
			#{RWN_rejectpt.p[2] = node->minmaxs[pindex[2]]};
			
			d = DotProduct (#{RWN_rejectpt.p}, #{view_clipplanes[i].normal.p});
			d -= #{view_clipplanes[i].dist};
			
			if (d <= 0) {
				return;
			}
			#{RWN_acceptpt.p[0] = node->minmaxs[pindex[3+0]]};
			#{RWN_acceptpt.p[1] = node->minmaxs[pindex[3+1]]};
			#{RWN_acceptpt.p[2] = node->minmaxs[pindex[3+2]]};

			d = DotProduct (#{RWN_acceptpt.p}, #{view_clipplanes[i].normal.p});
			d -= #{view_clipplanes[i].dist};

			if (d >= 0)
				clipflags &= ~(1<<i);	// node is entirely on screen
		}
	}

// if a leaf node, draw stuff
	if (#{node->contents} != -1)
	{
		pleaf = node;
		
		mark = #{pleaf->firstmarksurface};
		c = #{pleaf->nummarksurfaces};
		
		if (c > 0)
		{
			do
			{
				Memory.setI32(Memory.getI32(mark),r_framecount); // FIXME: IS THIS CORRECT?
				mark+=4;
			} while (--c > 0);
		}
		
		#{pleaf->key = r_currentkey};
		r_currentkey++;		// all bmodels in a leaf share the same key
	}
	else
	{
	// node is just a decision point, so go down the apropriate sides

	// find which side of the node we are on
		plane = #{node->plane};
		
		switch (#{plane->type})
		{
		case PLANE_X:
			dot = #{r_origin[0] - plane->dist};
		case PLANE_Y:
			dot = #{r_origin[1] - plane->dist};
		case PLANE_Z:
			dot = #{r_origin[2] - plane->dist};
		default:
			dot = DotProduct (#{r_origin}, #{plane->normal.p}) - #{plane->dist};
		}
		
		if (dot >= 0)
			side = 0;
		else
			side = 1;
		
	// recurse down the children, front side first
		R_RecursiveWorldNode (#{node->children[side]}, clipflags);
		
	// draw stuff
		c = #{node->numsurfaces};
		
		
		if (c > 0)
		{
			surf = #{&currentmodel->surfaces[node->firstsurface]};

			if (dot < -BACKFACE_EPSILON)
			{
				do
				{
					if ((#{surf->flags} & SURF_PLANEBACK) != 0 && #{surf->visframe} == r_framecount) 
					{
						R_RenderFace (surf, clipflags);
					}

					surf+=#{sizeof(msurface_t)};
				} while (--c > 0);
			}
			else if (dot > BACKFACE_EPSILON)
			{
				do
				{
					if ((#{surf->flags} & SURF_PLANEBACK) == 0 && #{surf->visframe} == r_framecount) 
					{
						R_RenderFace (surf, clipflags);
					}

					surf+=#{sizeof(msurface_t)};
				} while (--c > 0);
			}
		
		// all surfaces on the same node share the same sequence number
			r_currentkey++;
		}
		
	// recurse down the back side
		R_RecursiveWorldNode (#{node->children[-(#[--side]#)]}, clipflags);
	}
}
